{
 "cells": [
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "+++\n",
    "title = \"Correspondence analysis\"\n",
    "menu = \"main\"\n",
    "weight = 2\n",
    "toc = true\n",
    "aliases = [\"ca\"]\n",
    "+++"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Resources\n",
    "\n",
    "- [Theory of Correspondence Analysis](http://statmath.wu.ac.at/courses/CAandRelMeth/caipA.pdf) has all the equations.\n",
    "- [Correspondence analysis](https://cedric.cnam.fr/fichiers/art_3066.pdf) by Hervé Abdi and Michael Béra is great too, although it doesn't only cover CA.\n",
    "- [L’Analyse Factorielle des Correspondences (AFC)](https://marie-chavent.perso.math.cnrs.fr/wp-content/uploads/2013/10/AFC.pdf) by Marie Chavent is short and sweet."
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Data\n",
    "\n",
    "You can use correspondence analysis when you have a contingency table. In other words, when you want to analyse the dependency between two categorical variables. For instance, here is a dataset which counts the number of voters per region for each candidate in the 2022 French presidential elections."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-09-07T18:17:54.606822Z",
     "iopub.status.busy": "2024-09-07T18:17:54.606582Z",
     "iopub.status.idle": "2024-09-07T18:17:55.167913Z",
     "shell.execute_reply": "2024-09-07T18:17:55.167661Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th>candidate</th>\n",
       "      <th>Le Pen</th>\n",
       "      <th>Macron</th>\n",
       "      <th>Mélenchon</th>\n",
       "      <th>Abstention</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>region</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>Auvergne-Rhône-Alpes</th>\n",
       "      <td>943294</td>\n",
       "      <td>1175085</td>\n",
       "      <td>897434</td>\n",
       "      <td>1228490</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Bourgogne-Franche-Comté</th>\n",
       "      <td>409639</td>\n",
       "      <td>394117</td>\n",
       "      <td>277899</td>\n",
       "      <td>456682</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Bretagne</th>\n",
       "      <td>385393</td>\n",
       "      <td>647172</td>\n",
       "      <td>407527</td>\n",
       "      <td>543425</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Centre-Val de Loire</th>\n",
       "      <td>347845</td>\n",
       "      <td>383851</td>\n",
       "      <td>251259</td>\n",
       "      <td>459528</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Corse</th>\n",
       "      <td>42283</td>\n",
       "      <td>26795</td>\n",
       "      <td>19779</td>\n",
       "      <td>90636</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "candidate                Le Pen   Macron  Mélenchon  Abstention\n",
       "region                                                         \n",
       "Auvergne-Rhône-Alpes     943294  1175085     897434     1228490\n",
       "Bourgogne-Franche-Comté  409639   394117     277899      456682\n",
       "Bretagne                 385393   647172     407527      543425\n",
       "Centre-Val de Loire      347845   383851     251259      459528\n",
       "Corse                     42283    26795      19779       90636"
      ]
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import prince\n",
    "\n",
    "dataset = prince.datasets.load_french_elections()\n",
    "dataset[['Le Pen', 'Macron', 'Mélenchon', 'Abstention']].head()"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "☝️ *This dataset is already available as a contingency matrix. It's more common to have at one's disposal a flat dataset. If this is the case, a contigency matrix can be obtained using the `pivot_table` function in `pandas`.*"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Fitting"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-09-07T18:17:55.182512Z",
     "iopub.status.busy": "2024-09-07T18:17:55.182400Z",
     "iopub.status.idle": "2024-09-07T18:17:55.196930Z",
     "shell.execute_reply": "2024-09-07T18:17:55.195426Z"
    }
   },
   "outputs": [],
   "source": [
    "ca = prince.CA(\n",
    "    n_components=3,\n",
    "    n_iter=3,\n",
    "    copy=True,\n",
    "    check_input=True,\n",
    "    engine='sklearn',\n",
    "    random_state=42\n",
    ")\n",
    "ca = ca.fit(dataset)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Eigenvalues"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-09-07T18:17:55.209384Z",
     "iopub.status.busy": "2024-09-07T18:17:55.207679Z",
     "iopub.status.idle": "2024-09-07T18:17:55.251799Z",
     "shell.execute_reply": "2024-09-07T18:17:55.251040Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>eigenvalue</th>\n",
       "      <th>% of variance</th>\n",
       "      <th>% of variance (cumulative)</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>component</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>0.021</td>\n",
       "      <td>40.82%</td>\n",
       "      <td>40.82%</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>0.018</td>\n",
       "      <td>36.15%</td>\n",
       "      <td>76.97%</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>0.005</td>\n",
       "      <td>10.08%</td>\n",
       "      <td>87.04%</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "          eigenvalue % of variance % of variance (cumulative)\n",
       "component                                                    \n",
       "0              0.021        40.82%                     40.82%\n",
       "1              0.018        36.15%                     76.97%\n",
       "2              0.005        10.08%                     87.04%"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "ca.eigenvalues_summary"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Coordinates"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-09-07T18:17:55.257058Z",
     "iopub.status.busy": "2024-09-07T18:17:55.255686Z",
     "iopub.status.idle": "2024-09-07T18:17:55.277241Z",
     "shell.execute_reply": "2024-09-07T18:17:55.276087Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>0</th>\n",
       "      <th>1</th>\n",
       "      <th>2</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>region</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>Auvergne-Rhône-Alpes</th>\n",
       "      <td>-0.058638</td>\n",
       "      <td>0.038303</td>\n",
       "      <td>0.000937</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Bourgogne-Franche-Comté</th>\n",
       "      <td>-0.070815</td>\n",
       "      <td>-0.077604</td>\n",
       "      <td>-0.016357</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Bretagne</th>\n",
       "      <td>-0.083655</td>\n",
       "      <td>0.110491</td>\n",
       "      <td>-0.058991</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Centre-Val de Loire</th>\n",
       "      <td>-0.024624</td>\n",
       "      <td>-0.055799</td>\n",
       "      <td>-0.046167</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Corse</th>\n",
       "      <td>0.127370</td>\n",
       "      <td>-0.281755</td>\n",
       "      <td>0.279328</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                                0         1         2\n",
       "region                                               \n",
       "Auvergne-Rhône-Alpes    -0.058638  0.038303  0.000937\n",
       "Bourgogne-Franche-Comté -0.070815 -0.077604 -0.016357\n",
       "Bretagne                -0.083655  0.110491 -0.058991\n",
       "Centre-Val de Loire     -0.024624 -0.055799 -0.046167\n",
       "Corse                    0.127370 -0.281755  0.279328"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "ca.row_coordinates(dataset).head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-09-07T18:17:55.282166Z",
     "iopub.status.busy": "2024-09-07T18:17:55.281580Z",
     "iopub.status.idle": "2024-09-07T18:17:55.299614Z",
     "shell.execute_reply": "2024-09-07T18:17:55.298652Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>0</th>\n",
       "      <th>1</th>\n",
       "      <th>2</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>candidate</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>Arthaud</th>\n",
       "      <td>-0.034732</td>\n",
       "      <td>-0.091291</td>\n",
       "      <td>-0.122722</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Dupont-Aignan</th>\n",
       "      <td>-0.094708</td>\n",
       "      <td>-0.064696</td>\n",
       "      <td>-0.023546</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Hidalgo</th>\n",
       "      <td>-0.137897</td>\n",
       "      <td>0.052846</td>\n",
       "      <td>0.101351</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Jadot</th>\n",
       "      <td>-0.126228</td>\n",
       "      <td>0.188836</td>\n",
       "      <td>-0.031329</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Lassalle</th>\n",
       "      <td>-0.271867</td>\n",
       "      <td>-0.091407</td>\n",
       "      <td>0.365112</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                      0         1         2\n",
       "candidate                                  \n",
       "Arthaud       -0.034732 -0.091291 -0.122722\n",
       "Dupont-Aignan -0.094708 -0.064696 -0.023546\n",
       "Hidalgo       -0.137897  0.052846  0.101351\n",
       "Jadot         -0.126228  0.188836 -0.031329\n",
       "Lassalle      -0.271867 -0.091407  0.365112"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "ca.column_coordinates(dataset).head()"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Visualization"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-09-07T18:17:55.304130Z",
     "iopub.status.busy": "2024-09-07T18:17:55.303865Z",
     "iopub.status.idle": "2024-09-07T18:17:55.375708Z",
     "shell.execute_reply": "2024-09-07T18:17:55.374046Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "\n",
       "<div id=\"altair-viz-3ec12ac21d3d4428811dbf79789ccb92\"></div>\n",
       "<script type=\"text/javascript\">\n",
       "  var VEGA_DEBUG = (typeof VEGA_DEBUG == \"undefined\") ? {} : VEGA_DEBUG;\n",
       "  (function(spec, embedOpt){\n",
       "    let outputDiv = document.currentScript.previousElementSibling;\n",
       "    if (outputDiv.id !== \"altair-viz-3ec12ac21d3d4428811dbf79789ccb92\") {\n",
       "      outputDiv = document.getElementById(\"altair-viz-3ec12ac21d3d4428811dbf79789ccb92\");\n",
       "    }\n",
       "    const paths = {\n",
       "      \"vega\": \"https://cdn.jsdelivr.net/npm//vega@5?noext\",\n",
       "      \"vega-lib\": \"https://cdn.jsdelivr.net/npm//vega-lib?noext\",\n",
       "      \"vega-lite\": \"https://cdn.jsdelivr.net/npm//vega-lite@4.17.0?noext\",\n",
       "      \"vega-embed\": \"https://cdn.jsdelivr.net/npm//vega-embed@6?noext\",\n",
       "    };\n",
       "\n",
       "    function maybeLoadScript(lib, version) {\n",
       "      var key = `${lib.replace(\"-\", \"\")}_version`;\n",
       "      return (VEGA_DEBUG[key] == version) ?\n",
       "        Promise.resolve(paths[lib]) :\n",
       "        new Promise(function(resolve, reject) {\n",
       "          var s = document.createElement('script');\n",
       "          document.getElementsByTagName(\"head\")[0].appendChild(s);\n",
       "          s.async = true;\n",
       "          s.onload = () => {\n",
       "            VEGA_DEBUG[key] = version;\n",
       "            return resolve(paths[lib]);\n",
       "          };\n",
       "          s.onerror = () => reject(`Error loading script: ${paths[lib]}`);\n",
       "          s.src = paths[lib];\n",
       "        });\n",
       "    }\n",
       "\n",
       "    function showError(err) {\n",
       "      outputDiv.innerHTML = `<div class=\"error\" style=\"color:red;\">${err}</div>`;\n",
       "      throw err;\n",
       "    }\n",
       "\n",
       "    function displayChart(vegaEmbed) {\n",
       "      vegaEmbed(outputDiv, spec, embedOpt)\n",
       "        .catch(err => showError(`Javascript Error: ${err.message}<br>This usually means there's a typo in your chart specification. See the javascript console for the full traceback.`));\n",
       "    }\n",
       "\n",
       "    if(typeof define === \"function\" && define.amd) {\n",
       "      requirejs.config({paths});\n",
       "      require([\"vega-embed\"], displayChart, err => showError(`Error loading script: ${err.message}`));\n",
       "    } else {\n",
       "      maybeLoadScript(\"vega\", \"5\")\n",
       "        .then(() => maybeLoadScript(\"vega-lite\", \"4.17.0\"))\n",
       "        .then(() => maybeLoadScript(\"vega-embed\", \"6\"))\n",
       "        .catch(showError)\n",
       "        .then(() => displayChart(vegaEmbed));\n",
       "    }\n",
       "  })({\"config\": {\"view\": {\"continuousWidth\": 400, \"continuousHeight\": 300}}, \"layer\": [{\"data\": {\"name\": \"data-d312390d908ea87c4c7868bf6428b764\"}, \"mark\": {\"type\": \"circle\", \"size\": 50}, \"encoding\": {\"color\": {\"field\": \"variable\", \"type\": \"nominal\"}, \"tooltip\": [{\"field\": \"variable\", \"type\": \"nominal\"}, {\"field\": \"value\", \"type\": \"nominal\"}, {\"field\": \"component 0\", \"type\": \"quantitative\"}, {\"field\": \"component 1\", \"type\": \"quantitative\"}], \"x\": {\"axis\": {\"title\": \"component 0 \\u2014 40.82%\"}, \"field\": \"component 0\", \"scale\": {\"zero\": false}, \"type\": \"quantitative\"}, \"y\": {\"axis\": {\"title\": \"component 1 \\u2014 36.15%\"}, \"field\": \"component 1\", \"scale\": {\"zero\": false}, \"type\": \"quantitative\"}}, \"selection\": {\"selector001\": {\"type\": \"interval\", \"bind\": \"scales\", \"encodings\": [\"x\", \"y\"]}}}, {\"data\": {\"name\": \"data-2ed5d7f951e8f474bfab2ea5ef651df7\"}, \"mark\": {\"type\": \"circle\", \"size\": 50}, \"encoding\": {\"color\": {\"field\": \"variable\", \"type\": \"nominal\"}, \"tooltip\": [{\"field\": \"variable\", \"type\": \"nominal\"}, {\"field\": \"value\", \"type\": \"nominal\"}, {\"field\": \"component 0\", \"type\": \"quantitative\"}, {\"field\": \"component 1\", \"type\": \"quantitative\"}], \"x\": {\"axis\": {\"title\": \"component 0 \\u2014 40.82%\"}, \"field\": \"component 0\", \"scale\": {\"zero\": false}, \"type\": \"quantitative\"}, \"y\": {\"axis\": {\"title\": \"component 1 \\u2014 36.15%\"}, \"field\": \"component 1\", \"scale\": {\"zero\": false}, \"type\": \"quantitative\"}}}], \"$schema\": \"https://vega.github.io/schema/vega-lite/v4.17.0.json\", \"datasets\": {\"data-d312390d908ea87c4c7868bf6428b764\": [{\"component 0\": -0.05863780298801668, \"component 1\": 0.03830303368230363, \"component 2\": 0.0009370591424681387, \"variable\": \"region\", \"value\": \"Auvergne-Rh\\u00f4ne-Alpes\", \"label\": \"Auvergne-Rh\\u00f4ne-Alpes\"}, {\"component 0\": -0.07081540620096789, \"component 1\": -0.07760400138326755, \"component 2\": -0.016357191871767436, \"variable\": \"region\", \"value\": \"Bourgogne-Franche-Comt\\u00e9\", \"label\": \"Bourgogne-Franche-Comt\\u00e9\"}, {\"component 0\": -0.08365536312333344, \"component 1\": 0.11049076933986801, \"component 2\": -0.05899143896664786, \"variable\": \"region\", \"value\": \"Bretagne\", \"label\": \"Bretagne\"}, {\"component 0\": -0.024624010383987222, \"component 1\": -0.055798646523926465, \"component 2\": -0.046167156517519174, \"variable\": \"region\", \"value\": \"Centre-Val de Loire\", \"label\": \"Centre-Val de Loire\"}, {\"component 0\": 0.12737012338463027, \"component 1\": -0.2817548959977832, \"component 2\": 0.279327716704768, \"variable\": \"region\", \"value\": \"Corse\", \"label\": \"Corse\"}, {\"component 0\": -0.01345003092176253, \"component 1\": -0.13027486769172408, \"component 2\": -0.054477921810370956, \"variable\": \"region\", \"value\": \"Grand Est\", \"label\": \"Grand Est\"}, {\"component 0\": 0.8189510679942223, \"component 1\": -0.08691997985451963, \"component 2\": 0.08440370708450634, \"variable\": \"region\", \"value\": \"Guadeloupe\", \"label\": \"Guadeloupe\"}, {\"component 0\": 0.9093838803301523, \"component 1\": -0.1950870605684938, \"component 2\": 0.07489315003172993, \"variable\": \"region\", \"value\": \"Guyane\", \"label\": \"Guyane\"}, {\"component 0\": 0.013732211529156197, \"component 1\": -0.19010506642745578, \"component 2\": -0.07755899210438848, \"variable\": \"region\", \"value\": \"Hauts-de-France\", \"label\": \"Hauts-de-France\"}, {\"component 0\": 0.5699784467809029, \"component 1\": -0.1262013938400695, \"component 2\": 0.033328136590330494, \"variable\": \"region\", \"value\": \"La R\\u00e9union\", \"label\": \"La R\\u00e9union\"}, {\"component 0\": 0.8306524508683515, \"component 1\": -0.08346172586634251, \"component 2\": 0.07815647282613784, \"variable\": \"region\", \"value\": \"Martinique\", \"label\": \"Martinique\"}, {\"component 0\": 0.7144022982162033, \"component 1\": -0.4100858633003479, \"component 2\": -0.06288743013126619, \"variable\": \"region\", \"value\": \"Mayotte\", \"label\": \"Mayotte\"}, {\"component 0\": -0.0354287630950815, \"component 1\": -0.06746561826077299, \"component 2\": -0.07505732058608083, \"variable\": \"region\", \"value\": \"Normandie\", \"label\": \"Normandie\"}, {\"component 0\": -0.11050741584453627, \"component 1\": -0.00401169530016988, \"component 2\": 0.09797159429931881, \"variable\": \"region\", \"value\": \"Nouvelle-Aquitaine\", \"label\": \"Nouvelle-Aquitaine\"}, {\"component 0\": -0.07859242844479214, \"component 1\": -0.03331650668996927, \"component 2\": 0.14039467390087262, \"variable\": \"region\", \"value\": \"Occitanie\", \"label\": \"Occitanie\"}, {\"component 0\": -0.05614440291568972, \"component 1\": 0.0721610630991925, \"component 2\": -0.0860877935450618, \"variable\": \"region\", \"value\": \"Pays de la Loire\", \"label\": \"Pays de la Loire\"}, {\"component 0\": 0.011439418072918834, \"component 1\": -0.10658768661368064, \"component 2\": 0.029796011603662388, \"variable\": \"region\", \"value\": \"Provence-Alpes-C\\u00f4te d'Azur\", \"label\": \"Provence-Alpes-C\\u00f4te d'Azur\"}, {\"component 0\": 0.09161017774209065, \"component 1\": 0.2510566007649311, \"component 2\": -0.008996533461299479, \"variable\": \"region\", \"value\": \"\\u00cele-de-France\", \"label\": \"\\u00cele-de-France\"}], \"data-2ed5d7f951e8f474bfab2ea5ef651df7\": [{\"component 0\": -0.0347317570164994, \"component 1\": -0.09129069808968156, \"component 2\": -0.12272236550701432, \"variable\": \"candidate\", \"value\": \"Arthaud\", \"label\": \"Arthaud\"}, {\"component 0\": -0.09470816476067677, \"component 1\": -0.06469559978922397, \"component 2\": -0.02354582539132117, \"variable\": \"candidate\", \"value\": \"Dupont-Aignan\", \"label\": \"Dupont-Aignan\"}, {\"component 0\": -0.1378966441096638, \"component 1\": 0.05284614420997051, \"component 2\": 0.10135116000373637, \"variable\": \"candidate\", \"value\": \"Hidalgo\", \"label\": \"Hidalgo\"}, {\"component 0\": -0.12622833356116858, \"component 1\": 0.1888359673722402, \"component 2\": -0.03132921446867936, \"variable\": \"candidate\", \"value\": \"Jadot\", \"label\": \"Jadot\"}, {\"component 0\": -0.27186704959821606, \"component 1\": -0.09140713874793122, \"component 2\": 0.36511160560202327, \"variable\": \"candidate\", \"value\": \"Lassalle\", \"label\": \"Lassalle\"}, {\"component 0\": -0.11705635918325444, \"component 1\": -0.21567924032021216, \"component 2\": -0.03247599276352836, \"variable\": \"candidate\", \"value\": \"Le Pen\", \"label\": \"Le Pen\"}, {\"component 0\": -0.10602671271196822, \"component 1\": 0.10219861920069213, \"component 2\": -0.06565612842230388, \"variable\": \"candidate\", \"value\": \"Macron\", \"label\": \"Macron\"}, {\"component 0\": 0.09049166378851488, \"component 1\": 0.1625168200858184, \"component 2\": 0.04194401484185862, \"variable\": \"candidate\", \"value\": \"M\\u00e9lenchon\", \"label\": \"M\\u00e9lenchon\"}, {\"component 0\": -0.12418309730025906, \"component 1\": -0.01007426022720743, \"component 2\": -0.008082464284384704, \"variable\": \"candidate\", \"value\": \"Poutou\", \"label\": \"Poutou\"}, {\"component 0\": -0.06281907093170755, \"component 1\": 0.16385984822107902, \"component 2\": -0.020856517055489864, \"variable\": \"candidate\", \"value\": \"P\\u00e9cresse\", \"label\": \"P\\u00e9cresse\"}, {\"component 0\": -0.1716091272590023, \"component 1\": -0.034664844004597274, \"component 2\": 0.01832769271833674, \"variable\": \"candidate\", \"value\": \"Roussel\", \"label\": \"Roussel\"}, {\"component 0\": -0.09180172598570428, \"component 1\": 0.00880811429582139, \"component 2\": 0.08957315878600045, \"variable\": \"candidate\", \"value\": \"Zemmour\", \"label\": \"Zemmour\"}, {\"component 0\": 0.21068322752077778, \"component 1\": -0.07726647824246761, \"component 2\": 0.0009627111513000992, \"variable\": \"candidate\", \"value\": \"Abstention\", \"label\": \"Abstention\"}, {\"component 0\": -0.040778911154341936, \"component 1\": 0.012151459979702506, \"component 2\": -0.01637727185596052, \"variable\": \"candidate\", \"value\": \"Blank\", \"label\": \"Blank\"}]}}, {\"mode\": \"vega-lite\"});\n",
       "</script>"
      ],
      "text/plain": [
       "alt.LayerChart(...)"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "ca.plot(\n",
    "    dataset,\n",
    "    x_component=0,\n",
    "    y_component=1,\n",
    "    show_row_markers=True,\n",
    "    show_column_markers=True,\n",
    "    show_row_labels=False,\n",
    "    show_column_labels=False\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-09-07T18:17:55.383475Z",
     "iopub.status.busy": "2024-09-07T18:17:55.383064Z",
     "iopub.status.idle": "2024-09-07T18:17:55.448977Z",
     "shell.execute_reply": "2024-09-07T18:17:55.447103Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "\n",
       "<div id=\"altair-viz-a09a56db98e14dcb8c39f3fafcdd543e\"></div>\n",
       "<script type=\"text/javascript\">\n",
       "  var VEGA_DEBUG = (typeof VEGA_DEBUG == \"undefined\") ? {} : VEGA_DEBUG;\n",
       "  (function(spec, embedOpt){\n",
       "    let outputDiv = document.currentScript.previousElementSibling;\n",
       "    if (outputDiv.id !== \"altair-viz-a09a56db98e14dcb8c39f3fafcdd543e\") {\n",
       "      outputDiv = document.getElementById(\"altair-viz-a09a56db98e14dcb8c39f3fafcdd543e\");\n",
       "    }\n",
       "    const paths = {\n",
       "      \"vega\": \"https://cdn.jsdelivr.net/npm//vega@5?noext\",\n",
       "      \"vega-lib\": \"https://cdn.jsdelivr.net/npm//vega-lib?noext\",\n",
       "      \"vega-lite\": \"https://cdn.jsdelivr.net/npm//vega-lite@4.17.0?noext\",\n",
       "      \"vega-embed\": \"https://cdn.jsdelivr.net/npm//vega-embed@6?noext\",\n",
       "    };\n",
       "\n",
       "    function maybeLoadScript(lib, version) {\n",
       "      var key = `${lib.replace(\"-\", \"\")}_version`;\n",
       "      return (VEGA_DEBUG[key] == version) ?\n",
       "        Promise.resolve(paths[lib]) :\n",
       "        new Promise(function(resolve, reject) {\n",
       "          var s = document.createElement('script');\n",
       "          document.getElementsByTagName(\"head\")[0].appendChild(s);\n",
       "          s.async = true;\n",
       "          s.onload = () => {\n",
       "            VEGA_DEBUG[key] = version;\n",
       "            return resolve(paths[lib]);\n",
       "          };\n",
       "          s.onerror = () => reject(`Error loading script: ${paths[lib]}`);\n",
       "          s.src = paths[lib];\n",
       "        });\n",
       "    }\n",
       "\n",
       "    function showError(err) {\n",
       "      outputDiv.innerHTML = `<div class=\"error\" style=\"color:red;\">${err}</div>`;\n",
       "      throw err;\n",
       "    }\n",
       "\n",
       "    function displayChart(vegaEmbed) {\n",
       "      vegaEmbed(outputDiv, spec, embedOpt)\n",
       "        .catch(err => showError(`Javascript Error: ${err.message}<br>This usually means there's a typo in your chart specification. See the javascript console for the full traceback.`));\n",
       "    }\n",
       "\n",
       "    if(typeof define === \"function\" && define.amd) {\n",
       "      requirejs.config({paths});\n",
       "      require([\"vega-embed\"], displayChart, err => showError(`Error loading script: ${err.message}`));\n",
       "    } else {\n",
       "      maybeLoadScript(\"vega\", \"5\")\n",
       "        .then(() => maybeLoadScript(\"vega-lite\", \"4.17.0\"))\n",
       "        .then(() => maybeLoadScript(\"vega-embed\", \"6\"))\n",
       "        .catch(showError)\n",
       "        .then(() => displayChart(vegaEmbed));\n",
       "    }\n",
       "  })({\"config\": {\"view\": {\"continuousWidth\": 400, \"continuousHeight\": 300}}, \"layer\": [{\"mark\": {\"type\": \"circle\", \"size\": 0}, \"encoding\": {\"color\": {\"field\": \"variable\", \"type\": \"nominal\"}, \"tooltip\": [{\"field\": \"variable\", \"type\": \"nominal\"}, {\"field\": \"value\", \"type\": \"nominal\"}, {\"field\": \"component 0\", \"type\": \"quantitative\"}, {\"field\": \"component 1\", \"type\": \"quantitative\"}], \"x\": {\"axis\": {\"title\": \"component 0 \\u2014 40.82%\"}, \"field\": \"component 0\", \"scale\": {\"zero\": false}, \"type\": \"quantitative\"}, \"y\": {\"axis\": {\"title\": \"component 1 \\u2014 36.15%\"}, \"field\": \"component 1\", \"scale\": {\"zero\": false}, \"type\": \"quantitative\"}}, \"selection\": {\"selector002\": {\"type\": \"interval\", \"bind\": \"scales\", \"encodings\": [\"x\", \"y\"]}}}, {\"mark\": \"text\", \"encoding\": {\"text\": {\"field\": \"label\", \"type\": \"nominal\"}, \"x\": {\"axis\": {\"title\": \"component 0 \\u2014 40.82%\"}, \"field\": \"component 0\", \"scale\": {\"zero\": false}, \"type\": \"quantitative\"}, \"y\": {\"axis\": {\"title\": \"component 1 \\u2014 36.15%\"}, \"field\": \"component 1\", \"scale\": {\"zero\": false}, \"type\": \"quantitative\"}}}], \"data\": {\"name\": \"data-2ed5d7f951e8f474bfab2ea5ef651df7\"}, \"$schema\": \"https://vega.github.io/schema/vega-lite/v4.17.0.json\", \"datasets\": {\"data-2ed5d7f951e8f474bfab2ea5ef651df7\": [{\"component 0\": -0.0347317570164994, \"component 1\": -0.09129069808968156, \"component 2\": -0.12272236550701432, \"variable\": \"candidate\", \"value\": \"Arthaud\", \"label\": \"Arthaud\"}, {\"component 0\": -0.09470816476067677, \"component 1\": -0.06469559978922397, \"component 2\": -0.02354582539132117, \"variable\": \"candidate\", \"value\": \"Dupont-Aignan\", \"label\": \"Dupont-Aignan\"}, {\"component 0\": -0.1378966441096638, \"component 1\": 0.05284614420997051, \"component 2\": 0.10135116000373637, \"variable\": \"candidate\", \"value\": \"Hidalgo\", \"label\": \"Hidalgo\"}, {\"component 0\": -0.12622833356116858, \"component 1\": 0.1888359673722402, \"component 2\": -0.03132921446867936, \"variable\": \"candidate\", \"value\": \"Jadot\", \"label\": \"Jadot\"}, {\"component 0\": -0.27186704959821606, \"component 1\": -0.09140713874793122, \"component 2\": 0.36511160560202327, \"variable\": \"candidate\", \"value\": \"Lassalle\", \"label\": \"Lassalle\"}, {\"component 0\": -0.11705635918325444, \"component 1\": -0.21567924032021216, \"component 2\": -0.03247599276352836, \"variable\": \"candidate\", \"value\": \"Le Pen\", \"label\": \"Le Pen\"}, {\"component 0\": -0.10602671271196822, \"component 1\": 0.10219861920069213, \"component 2\": -0.06565612842230388, \"variable\": \"candidate\", \"value\": \"Macron\", \"label\": \"Macron\"}, {\"component 0\": 0.09049166378851488, \"component 1\": 0.1625168200858184, \"component 2\": 0.04194401484185862, \"variable\": \"candidate\", \"value\": \"M\\u00e9lenchon\", \"label\": \"M\\u00e9lenchon\"}, {\"component 0\": -0.12418309730025906, \"component 1\": -0.01007426022720743, \"component 2\": -0.008082464284384704, \"variable\": \"candidate\", \"value\": \"Poutou\", \"label\": \"Poutou\"}, {\"component 0\": -0.06281907093170755, \"component 1\": 0.16385984822107902, \"component 2\": -0.020856517055489864, \"variable\": \"candidate\", \"value\": \"P\\u00e9cresse\", \"label\": \"P\\u00e9cresse\"}, {\"component 0\": -0.1716091272590023, \"component 1\": -0.034664844004597274, \"component 2\": 0.01832769271833674, \"variable\": \"candidate\", \"value\": \"Roussel\", \"label\": \"Roussel\"}, {\"component 0\": -0.09180172598570428, \"component 1\": 0.00880811429582139, \"component 2\": 0.08957315878600045, \"variable\": \"candidate\", \"value\": \"Zemmour\", \"label\": \"Zemmour\"}, {\"component 0\": 0.21068322752077778, \"component 1\": -0.07726647824246761, \"component 2\": 0.0009627111513000992, \"variable\": \"candidate\", \"value\": \"Abstention\", \"label\": \"Abstention\"}, {\"component 0\": -0.040778911154341936, \"component 1\": 0.012151459979702506, \"component 2\": -0.01637727185596052, \"variable\": \"candidate\", \"value\": \"Blank\", \"label\": \"Blank\"}]}}, {\"mode\": \"vega-lite\"});\n",
       "</script>"
      ],
      "text/plain": [
       "alt.LayerChart(...)"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "ca.plot(\n",
    "    dataset,\n",
    "    x_component=0,\n",
    "    y_component=1,\n",
    "    show_row_markers=False,\n",
    "    show_column_markers=False,\n",
    "    show_row_labels=False,\n",
    "    show_column_labels=True\n",
    ")"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Contributions"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-09-07T18:17:55.458509Z",
     "iopub.status.busy": "2024-09-07T18:17:55.457962Z",
     "iopub.status.idle": "2024-09-07T18:17:55.485966Z",
     "shell.execute_reply": "2024-09-07T18:17:55.485696Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<style type=\"text/css\">\n",
       "</style>\n",
       "<table id=\"T_8733d\">\n",
       "  <thead>\n",
       "    <tr>\n",
       "      <th class=\"blank level0\" >&nbsp;</th>\n",
       "      <th id=\"T_8733d_level0_col0\" class=\"col_heading level0 col0\" >0</th>\n",
       "      <th id=\"T_8733d_level0_col1\" class=\"col_heading level0 col1\" >1</th>\n",
       "      <th id=\"T_8733d_level0_col2\" class=\"col_heading level0 col2\" >2</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th id=\"T_8733d_level0_row0\" class=\"row_heading level0 row0\" >Auvergne-Rhône-Alpes</th>\n",
       "      <td id=\"T_8733d_row0_col0\" class=\"data row0 col0\" >2%</td>\n",
       "      <td id=\"T_8733d_row0_col1\" class=\"data row0 col1\" >1%</td>\n",
       "      <td id=\"T_8733d_row0_col2\" class=\"data row0 col2\" >0%</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th id=\"T_8733d_level0_row1\" class=\"row_heading level0 row1\" >Bourgogne-Franche-Comté</th>\n",
       "      <td id=\"T_8733d_row1_col0\" class=\"data row1 col0\" >1%</td>\n",
       "      <td id=\"T_8733d_row1_col1\" class=\"data row1 col1\" >1%</td>\n",
       "      <td id=\"T_8733d_row1_col2\" class=\"data row1 col2\" >0%</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th id=\"T_8733d_level0_row2\" class=\"row_heading level0 row2\" >Bretagne</th>\n",
       "      <td id=\"T_8733d_row2_col0\" class=\"data row2 col0\" >2%</td>\n",
       "      <td id=\"T_8733d_row2_col1\" class=\"data row2 col1\" >4%</td>\n",
       "      <td id=\"T_8733d_row2_col2\" class=\"data row2 col2\" >4%</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th id=\"T_8733d_level0_row3\" class=\"row_heading level0 row3\" >Centre-Val de Loire</th>\n",
       "      <td id=\"T_8733d_row3_col0\" class=\"data row3 col0\" >0%</td>\n",
       "      <td id=\"T_8733d_row3_col1\" class=\"data row3 col1\" >1%</td>\n",
       "      <td id=\"T_8733d_row3_col2\" class=\"data row3 col2\" >2%</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th id=\"T_8733d_level0_row4\" class=\"row_heading level0 row4\" >Corse</th>\n",
       "      <td id=\"T_8733d_row4_col0\" class=\"data row4 col0\" >0%</td>\n",
       "      <td id=\"T_8733d_row4_col1\" class=\"data row4 col1\" >2%</td>\n",
       "      <td id=\"T_8733d_row4_col2\" class=\"data row4 col2\" >8%</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n"
      ],
      "text/plain": [
       "<pandas.io.formats.style.Styler at 0x165c9a290>"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "ca.row_contributions_.head().style.format('{:.0%}')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-09-07T18:17:55.487491Z",
     "iopub.status.busy": "2024-09-07T18:17:55.487390Z",
     "iopub.status.idle": "2024-09-07T18:17:55.497798Z",
     "shell.execute_reply": "2024-09-07T18:17:55.497559Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<style type=\"text/css\">\n",
       "</style>\n",
       "<table id=\"T_cac1a\">\n",
       "  <thead>\n",
       "    <tr>\n",
       "      <th class=\"blank level0\" >&nbsp;</th>\n",
       "      <th id=\"T_cac1a_level0_col0\" class=\"col_heading level0 col0\" >0</th>\n",
       "      <th id=\"T_cac1a_level0_col1\" class=\"col_heading level0 col1\" >1</th>\n",
       "      <th id=\"T_cac1a_level0_col2\" class=\"col_heading level0 col2\" >2</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th id=\"T_cac1a_level0_row0\" class=\"row_heading level0 row0\" >Arthaud</th>\n",
       "      <td id=\"T_cac1a_row0_col0\" class=\"data row0 col0\" >0%</td>\n",
       "      <td id=\"T_cac1a_row0_col1\" class=\"data row0 col1\" >0%</td>\n",
       "      <td id=\"T_cac1a_row0_col2\" class=\"data row0 col2\" >1%</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th id=\"T_cac1a_level0_row1\" class=\"row_heading level0 row1\" >Dupont-Aignan</th>\n",
       "      <td id=\"T_cac1a_row1_col0\" class=\"data row1 col0\" >1%</td>\n",
       "      <td id=\"T_cac1a_row1_col1\" class=\"data row1 col1\" >0%</td>\n",
       "      <td id=\"T_cac1a_row1_col2\" class=\"data row1 col2\" >0%</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th id=\"T_cac1a_level0_row2\" class=\"row_heading level0 row2\" >Hidalgo</th>\n",
       "      <td id=\"T_cac1a_row2_col0\" class=\"data row2 col0\" >1%</td>\n",
       "      <td id=\"T_cac1a_row2_col1\" class=\"data row2 col1\" >0%</td>\n",
       "      <td id=\"T_cac1a_row2_col2\" class=\"data row2 col2\" >3%</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th id=\"T_cac1a_level0_row3\" class=\"row_heading level0 row3\" >Jadot</th>\n",
       "      <td id=\"T_cac1a_row3_col0\" class=\"data row3 col0\" >3%</td>\n",
       "      <td id=\"T_cac1a_row3_col1\" class=\"data row3 col1\" >7%</td>\n",
       "      <td id=\"T_cac1a_row3_col2\" class=\"data row3 col2\" >1%</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th id=\"T_cac1a_level0_row4\" class=\"row_heading level0 row4\" >Lassalle</th>\n",
       "      <td id=\"T_cac1a_row4_col0\" class=\"data row4 col0\" >8%</td>\n",
       "      <td id=\"T_cac1a_row4_col1\" class=\"data row4 col1\" >1%</td>\n",
       "      <td id=\"T_cac1a_row4_col2\" class=\"data row4 col2\" >61%</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n"
      ],
      "text/plain": [
       "<pandas.io.formats.style.Styler at 0x165c92290>"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "ca.column_contributions_.head().style.format('{:.0%}')"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Cosine similarities"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-09-07T18:17:55.499157Z",
     "iopub.status.busy": "2024-09-07T18:17:55.499080Z",
     "iopub.status.idle": "2024-09-07T18:17:55.511761Z",
     "shell.execute_reply": "2024-09-07T18:17:55.511525Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>0</th>\n",
       "      <th>1</th>\n",
       "      <th>2</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>region</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>Auvergne-Rhône-Alpes</th>\n",
       "      <td>0.568331</td>\n",
       "      <td>0.242500</td>\n",
       "      <td>0.000145</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Bourgogne-Franche-Comté</th>\n",
       "      <td>0.365626</td>\n",
       "      <td>0.439086</td>\n",
       "      <td>0.019507</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Bretagne</th>\n",
       "      <td>0.212706</td>\n",
       "      <td>0.371061</td>\n",
       "      <td>0.105772</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Centre-Val de Loire</th>\n",
       "      <td>0.076356</td>\n",
       "      <td>0.392078</td>\n",
       "      <td>0.268406</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Corse</th>\n",
       "      <td>0.066825</td>\n",
       "      <td>0.327001</td>\n",
       "      <td>0.321391</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                                0         1         2\n",
       "region                                               \n",
       "Auvergne-Rhône-Alpes     0.568331  0.242500  0.000145\n",
       "Bourgogne-Franche-Comté  0.365626  0.439086  0.019507\n",
       "Bretagne                 0.212706  0.371061  0.105772\n",
       "Centre-Val de Loire      0.076356  0.392078  0.268406\n",
       "Corse                    0.066825  0.327001  0.321391"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "ca.row_cosine_similarities(dataset).head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-09-07T18:17:55.513059Z",
     "iopub.status.busy": "2024-09-07T18:17:55.512987Z",
     "iopub.status.idle": "2024-09-07T18:17:55.524906Z",
     "shell.execute_reply": "2024-09-07T18:17:55.524639Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>0</th>\n",
       "      <th>1</th>\n",
       "      <th>2</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>candidate</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>Arthaud</th>\n",
       "      <td>0.024619</td>\n",
       "      <td>0.170088</td>\n",
       "      <td>0.307375</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Dupont-Aignan</th>\n",
       "      <td>0.305277</td>\n",
       "      <td>0.142452</td>\n",
       "      <td>0.018869</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Hidalgo</th>\n",
       "      <td>0.292428</td>\n",
       "      <td>0.042947</td>\n",
       "      <td>0.157968</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Jadot</th>\n",
       "      <td>0.265642</td>\n",
       "      <td>0.594500</td>\n",
       "      <td>0.016364</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Lassalle</th>\n",
       "      <td>0.307040</td>\n",
       "      <td>0.034709</td>\n",
       "      <td>0.553774</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                      0         1         2\n",
       "candidate                                  \n",
       "Arthaud        0.024619  0.170088  0.307375\n",
       "Dupont-Aignan  0.305277  0.142452  0.018869\n",
       "Hidalgo        0.292428  0.042947  0.157968\n",
       "Jadot          0.265642  0.594500  0.016364\n",
       "Lassalle       0.307040  0.034709  0.553774"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "ca.column_cosine_similarities(dataset).head()"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": ".venv",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.4"
  },
  "vscode": {
   "interpreter": {
    "hash": "441c2ec70d9faeb70e7723f55150c6260f4a26a9c828b90915d3399002e14f43"
   }
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
